package cn.marknum.gateway.filter;

import cn.hutool.core.util.StrUtil;
import cn.marknum.web.ErrCode;
import cn.marknum.web.response.Response;
import cn.marknum.web.response.ResponseDSL;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.marknum.oauth.config.KoaiSecurityAutoConfiguration;
import com.marknum.oauth.util.CacheUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;

/**
 * 安管通道进行令牌获取
 *
 * @author zhangzhao    2022-09-16 09:58
 */
@Component
@ConditionalOnProperty(prefix = "oauth.koai", name = "enabled", havingValue = "true")
public class AGFilter implements WebFilter {

    private Logger logger = LoggerFactory.getLogger(getClass());

    @Value("${oauth.serverIp}")
    private String serverIp;
    @Value("${oauth.matchUrlPrefix}")
    private String matchUrlPrefix;
    private KoaiSecurityAutoConfiguration koaiSecurityAutoConfiguration;

    @Autowired
    public void setKoaiSecurityAutoConfiguration(KoaiSecurityAutoConfiguration koaiSecurityAutoConfiguration) {
        this.koaiSecurityAutoConfiguration = koaiSecurityAutoConfiguration;
    }

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
        String path = exchange.getRequest().getURI().getPath();
        if (path.contains(matchUrlPrefix)) {
            Object userToken = CacheUtils.get("userToken");
            Object appToken = CacheUtils.get("appToken");
            logger.info("userToken:{};appToken:{}", userToken, appToken);
            if (userToken == null || appToken == null) {
                synchronized (AGFilter.class) {
                    userToken = CacheUtils.get("userToken");
                    appToken = CacheUtils.get("appToken");
                    if (userToken == null || appToken == null) {
                        logger.info("===============重新获取格尔登录Token===============");
                        koaiSecurityAutoConfiguration.init();
                        userToken = CacheUtils.get("userToken");
                        appToken = CacheUtils.get("appToken");
                    }
                }
                logger.info("重新获取后：userToken:{};appToken:{}", userToken, appToken);
            }
            if (userToken == null || appToken == null) {
                return getVoidMono(exchange.getResponse());
            }
            ServerHttpRequest.Builder builder = exchange.getRequest().mutate();
            builder.header("RZZX-USERTOKEN", userToken.toString())
                    .header("RZZX-APPTOKEN", appToken.toString())
                    .header("x-real-ip", serverIp);
            return chain.filter(exchange.mutate().request(builder.build()).build());
        }
        return chain.filter(exchange);
    }

    private Mono<Void> getVoidMono(ServerHttpResponse serverHttpResponse) {
        serverHttpResponse.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
        Response responseResult = ResponseDSL.failure(ErrCode.PERMISSION_DEAD.getTipCode(), "未能获取格尔认证授权Token");
        DataBuffer dataBuffer =
                serverHttpResponse.bufferFactory().wrap(JSONObject.toJSONString(responseResult).getBytes(StandardCharsets.UTF_8));
        return serverHttpResponse.writeWith(Flux.just(dataBuffer));
    }
}
